package com.frinder.official.akka.routing;

import akka.routing.ConsistentHashingRouter;
import com.frinder.official.spring.MyBaseActor;
import com.google.common.collect.Maps;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import java.io.Serializable;
import java.util.Map;

/**
 * Created by frinder on 2017/9/29.
 */
@Component
@Scope("prototype")
public class Cache extends MyBaseActor {

    public static final String NOT_FOUND = "NOT_FOUND";

    Map<String, String> cache = Maps.newHashMap();

    @Override
    public Receive createReceive() {
        return receiveBuilder()
                .match(Entry.class, entry -> {
                    log.info("{} {} {}", getSender(), getSelf(), entry);
                    cache.put(entry.key, entry.value);
                })
                .match(Get.class, get -> {
                    Object value = cache.get(get.key);
                    log.info("{} {} {}-{}", getSender(), getSelf(), get, value);
                    getSender().tell(value == null ? NOT_FOUND : value, getSelf());
                })
                .match(Evict.class, evict -> {
                    log.info("{} {} {}", getSender(), getSelf(), evict);
                    cache.remove(evict.key);
                })
                .build();
    }


    public static final class Evict implements Serializable {
        private static final long serialVersionUID = 1L;
        public final String key;

        public Evict(String key) {
            this.key = key;
        }

        @Override
        public String toString() {
            return "Evict{" +
                    "key='" + key + '\'' +
                    '}';
        }
    }

    public static final class Get implements Serializable, ConsistentHashingRouter.ConsistentHashable {
        private static final long serialVersionUID = 1L;
        public final String key;

        public Get(String key) {
            this.key = key;
        }

        public Object consistentHashKey() {
            return key;
        }

        @Override
        public String toString() {
            return "Get{" +
                    "key='" + key + '\'' +
                    '}';
        }
    }

    public static final class Entry implements Serializable {
        private static final long serialVersionUID = 1L;
        public final String key;
        public final String value;

        public Entry(String key, String value) {
            this.key = key;
            this.value = value;
        }

        @Override
        public String toString() {
            return "Entry{" +
                    "key='" + key + '\'' +
                    ", value='" + value + '\'' +
                    '}';
        }
    }

}

